package com.fivefu.core.camera.services.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fivefu.base.common.utils.DateUtils;
import com.fivefu.base.common.utils.StrUtils;
import com.fivefu.base.fileupload.minio.services.MinioServices;
import com.fivefu.core.camera.properties.SnapeProperties;
import com.fivefu.core.camera.services.CameraVideoService;
import com.fivefu.core.camera.utils.CmdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
public class CameraVideoServiceImpl implements CameraVideoService {

    @Autowired
    private MinioServices minioServices;
    @Autowired
    private SnapeProperties snapeProperties;

    /**
     * 视频截图
     * @param cameraCode 探头编号
     * @param playUrl 视频播放地址
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> snapeCamera(String cameraCode, String playUrl) throws Exception {
        if (StrUtils.isNotNull(cameraCode)){
            cameraCode = UUID.randomUUID().toString();
        }
        String snapeUrl = snapeProperties.getUrl();
        String snapeFileName = snapeProperties.getFileName();

        String timestamp = DateUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss");
        String fileName = timestamp + ".jpg";
        String saveFile = snapeUrl + fileName;
        String cmd = snapeUrl + snapeFileName + " " + playUrl + " " + saveFile;
        if (CmdUtils.isLinux()){
            cmd = "/bin/bash " + cmd;
        }

        CmdUtils.execute(cmd);

        File file = new File(saveFile);
        if (file.exists()){
            InputStream inputStream = new FileInputStream(file);
            String url = minioServices.fileUpload(inputStream, fileName, "camera_snape/" + cameraCode, null);

            InputStream stream = new FileInputStream(file);
            BufferedImage image = ImageIO.read(stream);
            int width = image.getWidth();
            int height = image.getHeight();

            if (stream != null){
                stream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            file.delete();
            Map<String,Object> map = new HashMap<>();
            map.put("width", width);
            map.put("height", height);
            map.put("url", url);
            return map;
        }
        return null;
    }

    /**
     * 查询视频像素
     * @param playUrl 视频播放地址
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    public Map<String, Object> queryVideoPixel(String playUrl) throws IOException, InterruptedException {
        String cmd = "ffprobe -print_format json -show_streams " + playUrl + "";

        String result = CmdUtils.execute(cmd);

        Integer width = null, height = null;
        if (StrUtils.isNotNull(result) && result.contains("streams")) {
            if (result.contains("{")){
                result = result.substring(result.indexOf("{"));
            }
            JSONObject resultObj = JSONObject.parseObject(result);
            JSONArray streams = resultObj.getJSONArray("streams");
            if (streams != null) {
                for (int i = 0; i < streams.size(); i++) {
                    if (streams.getJSONObject(i).containsKey("width")) {
                        JSONObject stream = streams.getJSONObject(i);
                        width = stream.getInteger("width");
                        height = stream.getInteger("height");
                        break;
                    }
                }
            }
        }
        Map<String,Object> map = new HashMap<>();
        map.put("width", width);
        map.put("height", height);
        return map;
    }

}
